/**************************************************************************
*   Copyleft 2009 by        											  *
*	Iwanicki Krzysztof													  *
*   <www.gamma.mini.pw.edu.pl/~iwanickik>		                          *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
***************************************************************************/
#ifndef __VSCENEMANAGER_H__
#define __VSCENEMANAGER_H__

#include "../../Utils/vUtils.h"
#include "../Renderer/vFrameListener.h"
#include "../Viewport/vCamera.h"
#include "../../Macros/vMemoryMacros.h"

namespace Vendetta {
	class vLight;

	/*! \class vSceneManager
	 *  \brief A vSceneManager class contains all information about scene.
	 *
	 *  Manages camera, lighting creation, destruction and usage.
	 */
	class vSceneManager {
		friend class vEngine3D;
	public:
		/*! \brief Creates new camera.
		 *
		 *	Tries to create new camera with given name.
		 *	If camera with that name already exists returns vNull,
		 *	otherwise returns newly created one.
		 *	
		 *	\param		name				New camera name.
		 *	\return		vCamera*			Pointer to new camera.
		 *	\exception	vFatalException		When camera with that name already exists.
		 *	\sa			vCamera.
		 */	
		vCamera* CreateCamera(const vString& name);

		/*! \brief Removes and deletes camera from scene manager.
		 *
		 *	If camera for removing does not exists function will return false.
		 *
		 *	\param		vCamera*			Camera to remove.
		 *	\return		vBool				True if camera was removed, false otherwise.
		 *	\sa			vCamera.
		 */	
		vBool RemoveCamera(vCamera* pCamera);

		/*! \brief Removes and deletes camera from scene manager.
		 *
		 *	If camera for removing does not exists function will return false.
		 *
		 *	\param		name				Camera name to remove.
		 *	\return		vBool				True if camera was removed, false otherwise.
		 *	\sa			vCamera.
		 */	
		vBool RemoveCamera(const vString& name);

		/*! \brief Applies camera as current for viewing scene.
		 *
		 *	If camera for use does not exists vFataException is thrown.
		 *
		 *	\param		vCamera*			Camera to use.
		 *	\exception	vFatalException		When camera does not exists.
		 *	\sa			vCamera.
		 *	\sa			vFatalException.
		 */	
		vVoid UseCamera(vCamera* pCamera);

		/*! \brief Applies camera as current for viewing scene.
		 *
		 *	If camera for use does not exists vFataException is thrown.
		 *
		 *	\param		name				Camera to use.
		 *	\exception	vFatalException		When camera does not exists.
		 *	\sa			vCamera.
		 *	\sa			vFatalException.
		 */	
		vVoid UseCamera(const vString& name);

		/*! \brief Method called to update data before rendering starts.
		 *
		 *	\param		event				vFrameEvent structure containing useful information.
		 */
		vVoid Update(const vFrameListener::vFrameEvent& event);

		/*! \brief Prepares and applies camera.
		 *
		 */	
		vVoid SetupCamera();

		/*! \brief Enables / Disables frustum culling.
		 *
		 *	\param		bEnable				True if we want enable, false otherwise.
		 *	\sa			vFrustum.
		 */	
		inline vVoid EnableFrustumCulling(vBool bEnable) {
			mFrustumCullingOn = bEnable;
		}

		/*! \brief Checks whether frustum culling is enabled or not.
		 *
		 *	\return		vBool				True if is enabled, false otherwise.
		 *	\sa			vFrustum.
		 */	
		inline vBool IsFrustumCulling() const {
			return mFrustumCullingOn;
		}

		/*! \brief Returns active camera.
		 *
		 *	\return		vCamera*			Active camera pointer.
		 *	\sa			vCamera.
		 */	
		inline vCamera* ActiveCamera() {
			return mpActiveCamera;
		}
	
	protected:
		/*! \brief Default constructor.
		 *
		 */	
		vSceneManager();
	
		/*! \brief Destructor.
		 *
		 */	
		virtual ~vSceneManager();

		//! Disabled - if You call this You get exception.
		vSceneManager(const vSceneManager& sceneManager);

		//! Disabled - if You call this You get exception.
		vSceneManager& operator=(const vSceneManager& sceneManager);

	protected:
		vArray<vCamera*>				mCameras;			//!	Cameras list.
		vArray<vLight*>					mLights;			//! Lights list.
		vCamera*						mpActiveCamera;		//! Active camera.

		vBool							mFrustumCullingOn;	//! Is frustum culling enabled.
	
	};
}

#endif // __VSCENEMANAGER_H__